package com.loser.gateway.netty.biz;

import com.loser.gateway.base.Dispatcher;
import com.loser.module.base.proto.base.InnerRequest;
import com.loser.utils.trace.MDCUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

/**
 * @Desc 配置netty-handler
 * @Author loser
 * @Date 2021/3/2 9:30
 **/
@Slf4j
public class WebSocketNettyServerHandler extends SimpleChannelInboundHandler<InnerRequest> {

    private final Dispatcher dispatcher;

    public WebSocketNettyServerHandler(Dispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

    /**
     * 读取发送的消息
     *
     * @param ctx  通道上下文
     * @param base 信息内容
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, InnerRequest base) throws Exception {
        try {
            MDCUtil.setTraceId();
            base.setTraceId(MDCUtil.getTraceId());
            dispatcher.process(ctx, base);
        } finally {
            MDCUtil.removeTraceId();
        }
    }

    /**
     * 有新的连接上来的时候触发的操作
     *
     * @param ctx 通道上下文
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        log.info("WebSocketNettyServerHandler-handlerAdded-channel信息:{}", ctx.channel().toString());
    }

    /**
     * 连接断开的时候触发的操作
     *
     * @param ctx 通道上下文
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        log.info("WebSocketNettyServerHandler-handlerRemoved-channel信息:{}", ctx.channel().toString());
        clientOffline(ctx);
    }

    /**
     * 连接被激活的时候触发的操作
     *
     * @param ctx 通道上下文
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
    }

    /**
     * channel 断开连接的channel
     *
     * @param ctx 通道上下文
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
    }

    /**
     * 异常信息捕获
     *
     * @param ctx   通道上下文
     * @param cause 异常信息
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("WebSocketNettyServerHandler-exceptionCaught-Exception", cause);
        ctx.channel().close();
        clientOffline(ctx);
    }


    /**
     * 心跳检测事件
     *
     * @param ctx 通道上下文
     * @param evt 触发事件
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            switch (event.state()) {
                case READER_IDLE:
                    log.info("WebSocketNettyServerHandler-userEventTriggered-没有接收到:{}-的信息心跳信息，将断开连接回收资源", ctx.toString());
                    ctx.channel().close();
                    clientOffline(ctx);
                    break;
                case WRITER_IDLE:
                    log.info("WebSocketNettyServerHandler-userEventTriggered-写空闲");
                    break;
                case ALL_IDLE:
                    log.info("WebSocketNettyServerHandler-userEventTriggered-读写空闲");
                    break;
                default:
                    log.info("WebSocketNettyServerHandler-userEventTriggered-非法状态");
                    throw new IllegalStateException("非法状态！");
            }
        }
    }

    private void clientOffline(ChannelHandlerContext ctx) {
        // todo alan
    }

}
